﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.IO;
using System.Text;
using System.ComponentModel;
using System.Windows.Media.Imaging;
using System.Threading;
using System.Security.Cryptography;
using System.Windows.Threading;
using System.Windows;
using BrainTechLLC;
using BrainTechLLC.ThreadSafeObjects;
using AForge.Imaging.Filters;
using System.Windows.Media;
using System.Windows.Controls;

namespace WpfImageDuplicates
{
    public static class Util2
    {
        public static IFilter CreateFilter(this Type type)
        {
            var constructor = type.GetConstructor(Type.EmptyTypes);
            if (constructor != null)
            {
                IFilter filter = constructor.Invoke(null) as IFilter;
                return filter;
            }
            return null;
        }

        public static ImageSource CreateImageSourceFromBitmap(this Bitmap bm)
        {
            if (bm != null)
            {
                BitmapSizeOptions sizeOptions = BitmapSizeOptions.FromWidthAndHeight(bm.Width, bm.Height);
                return bm.CreateImageSourceFromBitmap(sizeOptions);
            }

            return null;
        }

        public static bool? GetIsVisibleInScroller(this DependencyObject dep, ScrollViewer scrollViewer)
        {
            if (scrollViewer == null)
                scrollViewer = (dep as FrameworkElement).FindParent<ScrollViewer>();

            System.Windows.Point p = new System.Windows.Point(0, 0);
            double viewportWidth = double.MaxValue;
            double viewportHeight = double.MaxValue;
            double verticalOffset = 0D;

            if (scrollViewer != null)
            {
                try
                {
                    GeneralTransform gt = (dep as Visual).TransformToVisual(scrollViewer);
                    p = gt.Transform(new System.Windows.Point(0, 0));
                    viewportWidth = scrollViewer.ViewportWidth;
                    viewportHeight = scrollViewer.ViewportHeight;
                    verticalOffset = scrollViewer.VerticalOffset;
                }
                catch
                {
                    return null;
                }
            }

            double thisActualHeight = (double)dep.GetValue(Control.ActualHeightProperty);
            bool retValue = (p.X < viewportWidth && p.Y + thisActualHeight > 0 && p.Y < viewportHeight);
            return retValue;
        }

        public static ImageSource CreateImageSourceFromBitmap(this Bitmap bm, BitmapSizeOptions sizeOptions)
        {
            if (bm != null)
            {
                IntPtr hBitmap = bm.GetHbitmap();              
                return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, sizeOptions);
            }

            return null;
        }

        public static bool CheckInitialization(this object lockObj, ref bool initialized, Action InitAction)
        {
            if (!initialized)
            {
                lock (lockObj)
                {
                    if (!initialized)
                    {
                        InitAction();
                        initialized = true;
                        return true;
                    }
                }
            }

            return false;
        }

        public static string CalculateMD5Hash(this byte[] bytes)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(bytes);
            ASCIIEncoding enc = new ASCIIEncoding();
            return enc.GetString(retVal);
        }

        public static void GetScaledSize(int x, int y, int maxX, int maxY, out int newX, out int newY)
        {
            double outX;
            double outY;
            GetScaledSize((double)x, (double)y, (double)maxX, (double)maxY, out outX, out outY);
            newX = Convert.ToInt32(Math.Floor(outX));
            newY = Convert.ToInt32(Math.Floor(outY));
        }

        public static void GetScaledSize(double x, double y, double maxX, double maxY, out double newX, out double newY)
        {
            double subtractPerX = y / x;
            while (x > maxX || y > maxY)
            {
                x -= 1.0D;
                y -= subtractPerX;
            }
            newX = x;
            newY = y;
        }

        public static List<T> GetSelected<T>(this ListBox listBox) where T : class
        {
            List<T> results = new List<T>();

            foreach (var item in listBox.SelectedItems)
            {
                var vm = item as T;
                results.Add(vm);
            }

            return results;
        }
    }

    public class ObjectEventArgs<T> : EventArgs // where T : class
    {
        public T obj { get; set; }

        public ObjectEventArgs() { }
        public ObjectEventArgs(T item) { obj = item; }
    }

    public class ObjectEventArgs<T1, T2> : EventArgs
        //where T1 : class
        //where T2 : class
    {
        public T1 obj1 { get; set; }
        public T2 obj2 { get; set; }

        public ObjectEventArgs() { }
        public ObjectEventArgs(T1 item1, T2 item2) { obj1 = item1; obj2 = item2; }
    }    
}
